/**
 * General utils, helper classes etc.
 * 
 * @author: Jannis Moßhammer <mojadev@googlemail.com>
 * @license: GPL Version 2
 */
var MojaUtils = MojaUtils || {};

MojaUtils.Logger = {
	log: function(msg) {
		try {
			if (window.console) {
				console.log(msg);
			}
		} catch(e) {
			//throw("No console available: LOG: "+msg);
		}
	}
	
}

MojaUtils.String = {
	unicodeAt : function(str,nr) {
		if(str.charCodeAt(nr) <= 0xff) // ASCII
			return str.charCodeAt(nr);
		if(!isNaN(str))
			return str;
	
		return parseInt(encodeURIComponent(str[nr]).replace(/%/g,''),16);	
	}	
}

MojaUtils.ExArray = function() {
	var arr = new Array();
	var cmpObject = function(elem1, elem2) {
		for(var i in elem1) {
			if (elem1[i] != elem2[i]) {
				return false;
			}
		}
		return true;
	}
	arr.addUniqueItem = function(item) {
		if(this.find(item) != -1)
			return;

		this.push(item);
	}

	arr.removeItem = function(item) {
		var pos = this.find(item);
		if (pos > -1) 
			this.removeAt(pos);
		
	}

	arr.find = function(item){
		for (var i = 0; i < this.length; i++) {
			if(this[i] == item)
				return i;
			if(typeof(item) == "object" || typeof(item) == "array")  	
				if (cmpObject(this[i],item)) 
					return i;
		}
		return -1;
	}
	
	arr.removeAt = function(pos) {
		return this.splice(pos,1);
	}
	
	return arr;
}

MojaUtils.Id = new function() {
	var ids = {};
	
	var createId = function() {
		var uid;
		do {
			uid = parseInt((Math.random()*100000)%100000,10);
		} while(ids[uid]);
		ids[uid] = true;
		return uid;
	}
	
	
	return createId;
}

MojaUtils.Observable = Class.create({
	
	initialize: function(){
		this.events = new MojaUtils.ExArray()
	},
		
	registerEvent : function(name,fn,scope,oneShot) {
		this.events.addUniqueItem({
			name: name,
			fn:fn, 
			scope: scope,
			oneShot: oneShot
		});
	},
	
	unregisterEvent: function(name,fn,scope,oneShot) {
		this.events.removeItem({
			name: name,
			fn:fn, 
			scope: scope,
			oneShot: oneShot
		});
	},
	
	fireEvent : function(name,args) {
		args = args || [];
		if(!args.length)
			args = [args];
		for(var i=0;i<this.events.length;i++) {
			if(this.events[i].name == name)
				this.__fnByEvent(this.events[i],args);
		}
		this.clearEvents();
	},
	
	clearEvents: function(all){
		if(all)
			this.events = new MojaUtils.ExArray();
		for(var i=0;i<this.events.length;i++) {
			if (this.events[i].killMe) {
				this.events.removeAt(i);
				i = 0;
			}
		}
	},
	
	__fnByEvent : function(ev,args) {
		ev.fn.apply(ev.scope,args);
		if(ev.oneShot)
			ev.killMe = true;
	}
});

/**
 * A wrapper around WebSockets.
 * If any changes in the api occur, those could be handled here.
 * 
 **/
if (WebSocket) {
	MojaUtils.Socket = Class.create(MojaUtils.Observable, {
		__Socket: null,

		initialize: function() {
			this.__Socket = null;
			this.status = "started";
			this.uid = MojaUtils.Id();
			MojaUtils.Observable.prototype.initialize.call(this);
		},
		
		connect: function(host, port){
			this.__Socket = new WebSocket(host + (port ? ":" + port : ""));
			this.__Socket.binaryType = "blob"
            this.initEvents();
		},
		
		initEvents: function() {
			var sc = this;
			fr = new FileReader();
            fr.onloadend = function(ev) {
                
                sc.fireEvent("recv",[ev.target.result]);
            }
            this.__Socket.onopen = function() {
				sc.status = "open";
				sc.fireEvent("onopen");
			};
			this.__Socket.onerror = function() {
				sc.status = "error";
				sc.fireEvent("onerror");
			};
			this.__Socket.onclose = function() {
				sc.status = "closed";
				sc.fireEvent("onclose");
			};
			this.__Socket.onmessage = function(msg) {                 
                console.log(msg);
                fr.readAsText(msg.data);
            };
		},
		
		close: function(cb){
			this.__Socket.close();
			console.log("Closing socket");	
		},
		
		send: function(msg){
			if(this.status == "open")
				this.__Socket.send(msg);
			
		
		},
		
		recv: function(cb) {
			this.registerEvent("recv",cb.fn,cb.scope,true);
		},
		
		recvForever: function(cb) {
			this.registerEvent("recv",cb.fn,cb.scope,false);
		}
	});
} else {
	alert("Sorry, your Browser doesn't seem to support WebSockets");
	throw("Sorry, your Browser doesn't seem to support WebSockets");
} 

